package com.uwlaser.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.uwlaser.domain.*;
import com.uwlaser.service.ProductParamsService;
import com.uwlaser.service.dto.*;
import com.uwlaser.service.mapper.*;
import com.uwlaser.utils.FileUtil;
import com.uwlaser.utils.enums.DictValueEnum;
import lombok.AllArgsConstructor;
import com.uwlaser.base.PageInfo;
import com.uwlaser.base.QueryHelpMybatisPlus;
import com.uwlaser.base.impl.CommonServiceImpl;
import com.uwlaser.utils.ConvertUtil;
import com.uwlaser.utils.PageUtil;
import com.uwlaser.service.DataMainService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
// 默认不使用缓存
//import org.springframework.cache.annotation.CacheConfig;
//import org.springframework.cache.annotation.CacheEvict;
//import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author zk-Qin
* @date 2022-05-11
*/
@Service
@AllArgsConstructor
// @CacheConfig(cacheNames = DataMainService.CACHE_KEY)
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class DataMainServiceImpl extends CommonServiceImpl<DataMainMapper, DataMain> implements DataMainService {

    // private final RedisUtils redisUtils;
    private final DataMainMapper dataMainMapper;

    private final DataMaterialSingleMapper dataMaterialSingleMapper;

    private final DataMaterialBatchMapper dataMaterialBatchMapper;

    private final CraftParamMapper craftParamMapper;

    private final CraftParamDetailMapper craftParamDetailMapper;

    private final ProductParamsService productParamsService;

    private final ProductParamsMapper productParamsMapper;

    @Override
    public PageInfo<DataMainDto> queryAll(DataMainQueryParam query, Pageable pageable) {
        IPage<DataMain> queryPage = PageUtil.toMybatisPage(pageable);
        IPage<DataMain> page = dataMainMapper.selectPage(queryPage, QueryHelpMybatisPlus.getPredicate(query));
        PageInfo<DataMainDto> pageInfo = ConvertUtil.convertPage(page, DataMainDto.class);
        pageInfo.getContent().forEach( dataMainDto -> {
            Set<CraftParamDetailDto> craftParamDetailDtoSet = ConvertUtil.convertSet(
                    craftParamDetailMapper.queryCraftParamDetail(dataMainDto.getProductCode()), CraftParamDetailDto.class);
            dataMainDto.setCraftParam(craftParamDetailDtoSet);
        });
        return pageInfo;
    }

    @Override
    public List<DataMainDto> queryAll(DataMainQueryParam query){
        return ConvertUtil.convertList(dataMainMapper.selectList(QueryHelpMybatisPlus.getPredicate(query)), DataMainDto.class);
    }

    @Override
    public DataMain getById(Integer id) {
        return dataMainMapper.selectById(id);
    }

    @Override
    // @Cacheable(key = "'id:' + #p0")
    public DataMainDto findById(Integer id) {
        return ConvertUtil.convert(getById(id), DataMainDto.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(DataMainDto resources) {
        DataMain entity = ConvertUtil.convert(resources, DataMain.class);
        return dataMainMapper.insert(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateById(DataMainDto resources){
        DataMain entity = ConvertUtil.convert(resources, DataMain.class);
        int ret = dataMainMapper.updateById(entity);
        // delCaches(resources.id);
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeByIds(Set<Integer> ids){
        // delCaches(ids);
        return dataMainMapper.deleteBatchIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeById(Integer id){
        Set<Integer> set = new HashSet<>(1);
        set.add(id);
        return this.removeByIds(set);
    }

    /*
    private void delCaches(Integer id) {
        redisUtils.delByKey(CACHE_KEY + "::id:", id);
    }

    private void delCaches(Set<Integer> ids) {
        for (Integer id: ids) {
            delCaches(id);
        }
    }*/

    @Override
    public void download(List<DataMainDto> all, HttpServletResponse response) throws IOException {
      List<Map<String, Object>> list = new ArrayList<>();
      for (DataMainDto dataMain : all) {
        Map<String,Object> map = new LinkedHashMap<>();
              map.put("产品SN", dataMain.getProductSn());
              map.put("产品型号", dataMain.getProductCode());
              map.put("产品类型", dataMain.getProductType());
              map.put("订单编号", dataMain.getOrderCode());
              map.put("工单编号", dataMain.getWorkOrderCode());
              String result=null;
              switch (dataMain.getResult()){
                  case "0" :result=DictValueEnum.RESULT_NG.getLabel();break;
                  case "1" :result=DictValueEnum.RESULT_OK.getLabel();break;
                  case "2" :result=DictValueEnum.RESULT_UN.getLabel();break;
                  case "3" :result=DictValueEnum.RESULT_SC.getLabel();break;
                  default : result="null";
              }
              map.put("结果", result);
              map.put("产线编号", dataMain.getLienCode());
              map.put("工段编号", dataMain.getSectionCode());
              map.put("开始加工时间", dataMain.getStartTime());
              map.put("结束加工时间", dataMain.getEndTime());
              map.put("工艺路线编号", dataMain.getPathCode());
              map.put("工艺路线版本", dataMain.getPathVersion());
              map.put("工艺参数编号", dataMain.getParamsCode());
              map.put("工艺参数版本", dataMain.getParamsVersion());
              map.put("BOM编号", dataMain.getBomCode());
              map.put("BOM版本", dataMain.getBomVersion());
//              map.put("预留1", dataMain.getUntitled1());
//              map.put("通道", dataMain.getAisleCode());
              map.put("托盘", dataMain.getTrayCode());
              map.put("创建人", dataMain.getCreateBy());
              map.put("创建时间", dataMain.getCreateTime());
//              map.put("更新人", dataMain.getUpdateBy());
//              map.put("更新时间", dataMain.getUpdateTime());
        list.add(map);
      }
      FileUtil.downloadExcel(list, response);
    }

    /**
     * 获取物料树
     * @param query
     * @return
     */
    @Override
    public MaterialTreeVo getMaterialTree(MaterialTreeVo query) {
        //1.获得条码主要信息
        int id = 1;
        DataMain dataMain = new DataMain();
        dataMain.setProductSn(query.getProductSn());
        QueryWrapper<DataMain> queryWrapper = new QueryWrapper<>(dataMain);
        DataMain mainSn = dataMainMapper.selectOne(queryWrapper);

        //1.1判断条码是什么类型的条码（电芯、模组、电池包）
        String materialName;
        switch (mainSn.getProductType()) {
            case "C":materialName="电芯"; break;
            case "M":materialName="模组"; break;
            case "P":materialName="电池包"; break;
            default: materialName="未知类型"; break;
        }

        MaterialTreeVo treeVo = new MaterialTreeVo();
        treeVo.setId(id);
        treeVo.setProductSn(query.getProductSn());
        treeVo.setMaterialName(materialName);
        treeVo.setMaterialSn(query.getProductSn());
        treeVo.setMaterialCode(mainSn.getProductCode());
        treeVo.setCodeType("1");

        List<MaterialTreeVo> children = new ArrayList<>();

        if(query.getRetrospect().equals("1")){ //正向追溯
            //获取物料单件码
            DataMaterialSingle materialSingle = new DataMaterialSingle();
            materialSingle.setProductSn(query.getProductSn());
            QueryWrapper<DataMaterialSingle> singleQueryWrapper = new QueryWrapper<>(materialSingle);
            List<DataMaterialSingle> singlesList = dataMaterialSingleMapper.selectList(singleQueryWrapper);
            if(singlesList != null && singlesList.size() > 0){
                for (DataMaterialSingle single : singlesList) {
                    id ++;
                    MaterialTreeVo treeNode = new MaterialTreeVo();
                    treeNode.setId(id);
                    treeNode.setProductSn(single.getProductSn());
                    treeNode.setMaterialName(single.getMaterialName());
                    treeNode.setMaterialCode(single.getMaterialCode());
                    treeNode.setMaterialSn(single.getMaterialSn());
                    treeNode.setCodeType("1");
                    children.add(treeNode);
                }
            }
            DataMaterialBatch materialBatch = new DataMaterialBatch();
            materialBatch.setProductSn(query.getProductSn());
            QueryWrapper<DataMaterialBatch> batchQueryWrapper = new QueryWrapper<>(materialBatch);
            List<DataMaterialBatch> batchesList = dataMaterialBatchMapper.selectList(batchQueryWrapper);
            if(batchesList != null && batchesList.size() > 0){
                for (DataMaterialBatch batch : batchesList) {
                    id ++;
                    MaterialTreeVo treeNode = new MaterialTreeVo();
                    treeNode.setId(id);
                    treeNode.setProductSn(batch.getProductSn());
                    treeNode.setMaterialName(batch.getMaterialName());
                    treeNode.setMaterialCode(batch.getMaterialCode());
                    treeNode.setMaterialSn(batch.getMaterialSn());
                    treeNode.setCodeType("2");
                    children.add(treeNode);
                }
            }
            treeVo.setChildren(children);
        }else{//返向追溯
            DataMaterialSingle materialSingle = new DataMaterialSingle();
            materialSingle.setMaterialSn(query.getProductSn());
            QueryWrapper<DataMaterialSingle> singleQueryWrapper = new QueryWrapper<>(materialSingle);
            //查询模组码
            DataMaterialSingle single = dataMaterialSingleMapper.selectOne(singleQueryWrapper);
            if(single != null ){
                id ++;
                MaterialTreeVo mTree =  new MaterialTreeVo();
                mTree.setId(id);
                mTree.setMaterialCode(single.getProductCode());
                switch (mainSn.getProductType()) {
                    case "C":mTree.setMaterialName("模组"); break;
                    case "M":mTree.setMaterialName("电池包"); break;
                    case "P":
                    default: mTree.setMaterialName("未知类型"); break;
                }

                mTree.setMaterialSn(single.getProductSn());
                mTree.setCodeType("1");
                treeVo.setChildren(Arrays.asList(mTree));

                DataMaterialSingle packSingle = new DataMaterialSingle();
                packSingle.setMaterialSn(single.getProductSn());
                DataMaterialSingle single2 = dataMaterialSingleMapper.selectOne(new QueryWrapper<>(packSingle));
                if(single2 != null){
                    id ++;
                    MaterialTreeVo pTree =  new MaterialTreeVo();
                    pTree.setId(id);
                    pTree.setMaterialCode(single2.getProductCode());
                    switch (mainSn.getProductType()) {
                        case "C":pTree.setMaterialName("电池包"); break;
                        case "M":
                        case "P":
                        default: pTree.setMaterialName("未知类型"); break;
                    }
                    pTree.setMaterialSn(single2.getProductSn());
                    pTree.setCodeType("1");
                    mTree.setChildren(Arrays.asList(pTree));
                }
            }
        }
        return treeVo;
    }

    @Override
    public List<DataMainDto> queryProductSn(DataMainQueryParam query) {
        return dataMainMapper.selectProductSn(query);
    }

    @Override
    public List<DataMainDto> queryPackSn(DataMainQueryParam query) {
        return dataMainMapper.selectPackSn(query);
    }

    @Override
    public CraftParamDto getCraftParamId(String productCode) {
        return ConvertUtil.convert(craftParamMapper.lambdaQuery().eq(CraftParam::getProductCode,productCode).one(),CraftParamDto.class);
    }

    @Override
    public void updateProduct(DataMainDto resources){
        ProductParams productParams = new ProductParams();
        List<Integer> oldProductParamIds = productParamsService.queryProductIdByParamId(Integer.valueOf(resources.getId()));
        List<Integer> productParamIds = resources.getCraftParam().stream().map(CraftParamDetailDto::getId).collect(Collectors.toList());
        List<Integer> deleteList = oldProductParamIds.stream().filter(item -> !productParamIds.contains(item)).collect(Collectors.toList());
        List<Integer> addList = productParamIds.stream().filter(item -> !oldProductParamIds.contains(item)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(deleteList)) {
            productParamsService.lambdaUpdate()
                    .eq(ProductParams::getProductModelId, resources.getId())
                    .in(ProductParams::getParamDetailId, deleteList).remove();
        }
         // 循环添加产品和参数关系
        addList.forEach(item -> {
            productParams.setParamDetailId(item);
            productParams.setProductModelId(Integer.valueOf(resources.getId()));
            productParamsMapper.insert(productParams);
        });
    }
}
